#ifndef __WRAPPER_H__
#define __WRAPPER_H__

#include <cassert>
#include <iostream>
#include <array>

using namespace std;

class Runnable {
public:
  virtual void operator()() {
    std::cerr << "Need derived class" << endl;
    assert(false);
  }
  friend ostream &operator<<(ostream &os, Runnable &);

protected:
  // Virtual friend idiom
  virtual void print(ostream &os) {
    std::cerr << "Need derived class" << endl;
    assert(false);    
  }
};

template <int TASK_ID, int NPARAMS, int TASKTAGDIM, int INTERTASKDIM>
class PolyTask : public Runnable {
  int id = TASK_ID;
  void *arrayPtr;
  std::array<int64_t, NPARAMS> params;

public:
  template <typename... Sizes> 
  PolyTask(void *a, Sizes... sizes) : arrayPtr(a), params{{std::forward<Sizes>(sizes)...}} {
    static_assert(NPARAMS == sizeof...(Sizes), "ERROR");
    assert(arrayPtr != nullptr);
  }

  void operator()();
  
protected:
  // Virtual 
  void print(ostream &os) {
    os << "CnC version";
  }
};
#endif // __WRAPPER_H__
